<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
td {
	width: 80px;
	height: 35px;
	border: 1px solid #0017B5;
	text-align: center;
	font-size: 13px;
}

.selected {
	border: 2px solid #000055;
	background-color:#BFE87E;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/jquery"></script>
<script src="https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
</head>
<body>

<table id="mytable" onclick="toInput(event)" style="border-collapse: collapse">
<tr>
	<td></td>
	<td></td>
	<td></td>
</tr>
<tr>
	<td></td>
	<td></td>
	<td></td>
</tr>
</table>

<p id="showPos"></p>  <!-- 光标移入时显示当前位置 -->
<p id="showModifyPos" style="color: red;"></p>  <!-- 编辑时显示当前编辑位置 -->

<button onclick="exportAsXlsx()">导出为excel表格</button>
<button onclick="print()">打印表格</button>

</body>
<script>
	var lastSelected = null;

	//单元格点击事件
	function toInput(e) {
		e.stopPropagation();
		var obj = e.target || e.srcElement;
		if (obj.tagName.toUpperCase() != 'TD') {
			return ;
		}
		var td = $(obj);
		
		if (lastSelected != null) {
			lastSelected.removeClass("selected");
			lastSelected = td;
		} else {
			lastSelected = td;
		}
		td.addClass("selected");
		
		tdWrite(td);
	}
	
	//单元格变成可输入
	function tdWrite(td) {
		td.html("<input class='tdinput' style='width:100%;height:100%;border:0px;' oninput='getModifyPosition(this)' onblur='inputComplete(this)' value=" + td.text() + ">");
		td.find("input").first().focus();  //获取输入焦点
		getPosition(td.find("input").first());
		
		//输入框绑定回车事件
		$(".tdinput").each(function() {
			this.onkeyup = function(e) {
				e.stopPropagation();
				var code = e.charCode || e.keyCode;
				if (code == 13 || code == 39) {  //回车或 →
					moveRight(this);
					inputComplete(this);
				} else if (code == 37) {  //←
					moveLeft(this);
					inputComplete(this);
				} else if (code == 38) {  //↑
					moveUp(this);
					inputComplete(this);
				} else if (code == 40) {  //↓
					moveDown(this);
					inputComplete(this);
				}
			}
		});
	}
	
	//移到上面一格(参数i：输入框)
	function moveUp(i) {
		var nextTd = $($(i).parent().parent().prev().children().get(currentCol - 1));
		if (nextTd.length == 0) {  //到最顶一格了
			inputComplete(i);
			return ;
		}
		tdWrite(nextTd);
	}
	
	//移到下面一格(参数i：输入框)
	function moveDown(i) {
		var nextTd = $($(i).parent().parent().next().children().get(currentCol - 1));
		if (nextTd.length == 0) {  //到最下方一格了
			inputComplete(i);
			return ;
		}
		tdWrite(nextTd);
	}
	
	//移到左边一格(参数i：输入框)
	function moveLeft(i) {
		var nextTd = $(i).parent().prev();
		if (nextTd.length == 0) {  //到最左一格了
			inputComplete(i);
			return ;
		}
		tdWrite(nextTd);
	}
	
	//移到右边一格(参数i：输入框)
	function moveRight(i) {
		var nextTd = $(i).parent().next().length!=0?
						$(i).parent().next()
						: $(i).parent().parent().next().find("td").first();
		if (nextTd.length == 0) {  //到最后一格了
			//新增一行
			let colNum = $(i).parent().prevAll().length + 1;
			let newRow = "";
			for (let i = 0; i < colNum; i++) {
				newRow += '<td></td>';
			}
			newRow = '<tr>' + newRow + '</tr>';
			$("#mytable").append(newRow);
			//光标即将移到新一行起始格
			nextTd = $(i).parent().parent().next().find("td").first();
		}
		tdWrite(nextTd);
	}
	
	//完成输入后将输入框内容写入表格(参数i：输入框)
	function inputComplete(i) {
		$(i).parent().html(i.value);
		// $("#showPos").html("");
		$("#showModifyPos").html("");
	}
	
	// var currentRow;
	var currentCol;
	//显示行列(参数i：输入框)
	function getPosition(i) {
		let rows = $(i).parent().parent().prevAll().length + 1;
		// currentRow = rows;
		let cols = $(i).parent().prevAll().length + 1;
		currentCol = cols;
		$("#showPos").html("当前行: " + rows + "，" + "列: " + cols);
	}
	
	//显示修改中行列(参数i：输入框)
	function getModifyPosition(i) {
		let rows = $(i).parent().parent().prevAll().length + 1;
		let cols = $(i).parent().prevAll().length + 1;
		$("#showModifyPos").html("当前修改行: " + rows + "，" + "列: " + cols);
	}
	
	//*****************************************************************************
	//参考https://blog.csdn.net/quyunde/article/details/80654687
	
	var tableStyle = "<style>td{width:80px;height:35px;border:1px solid #0017B5;text-align:center;font-size:13px;}</style></head><body>";
	
	//导出为表格
	function exportAsXlsx() {
		let table = "<html><head><meta charset='utf-8' />"
					+ tableStyle
					+ document.querySelector("#mytable").outerHTML
					+ "</body></html>";
		let blob = new Blob([table], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
		saveAs(blob, "export.xlsx");
	}
	
	//打印
	function print() {
		let newWindow = window.open();
		newWindow.focus();
		let content = "<html><head><meta charset='utf-8'/><title>打印</title>"
						+ tableStyle
						+ document.querySelector("#mytable").outerHTML
						+ "</body></html>";
				
		newWindow.document.write(content);
		newWindow.print();
		newWindow.document.close();
		newWindow.close();
		return false;
	}
</script>
</html>